package com.ruoyi.business.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.ruoyi.business.domain.HistoricActivity;
import com.ruoyi.business.domain.ServiceItem;
import com.ruoyi.business.service.IDefinitionNodeService;
import com.ruoyi.business.service.IProcessService;
import com.ruoyi.business.service.IServiceItemService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysUserService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.CarPackageAuditMapper;
import com.ruoyi.business.domain.CarPackageAudit;
import com.ruoyi.business.service.ICarPackageAuditService;
import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * 审核列表Service业务层处理
 * 
 * @author wolfcode
 * @date 2021-08-27
 */
@Service
public class CarPackageAuditServiceImpl implements ICarPackageAuditService 
{
    @Autowired
    private CarPackageAuditMapper carPackageAuditMapper;

    @Autowired
    private IProcessService processService;

    @Autowired
    private IServiceItemService serviceItemService;

    @Autowired
    private IDefinitionNodeService definitionNodeService;

    @Autowired
    private SysUserMapper sysUserMapper;


    /**
     * 查询审核列表
     * 
     * @param id 审核列表ID
     * @return 审核列表
     */
    @Override
    public CarPackageAudit selectCarPackageAuditById(Long id)
    {
        return carPackageAuditMapper.selectCarPackageAuditById(id);
    }

    /**
     * 查询审核列表列表
     * 
     * @param carPackageAudit 审核列表
     * @return 审核列表
     */
    @Override
    public List<CarPackageAudit> selectCarPackageAuditList(CarPackageAudit carPackageAudit) {
        List<CarPackageAudit> carMaintenanceInfos = carPackageAuditMapper.selectCarPackageAuditList(carPackageAudit);
        Task task = null;
        for(CarPackageAudit audit:carMaintenanceInfos){
            audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class));
            //根据流程实例id查询当前任务
            task = processService.getTaskByInstanceId(audit.getInstanceId());
            if(task!=null){
                audit.setTaskId(task.getId());
                audit.setTaskName(task.getName());
            }else{
                audit.setTaskName("已结束");
            }
        }
        return carMaintenanceInfos;
    }

    /**
     * 新增审核列表
     * 
     * @param carPackageAudit 审核列表
     * @return 结果
     */
    @Override
    public int insertCarPackageAudit(CarPackageAudit carPackageAudit)
    {
        carPackageAudit.setCreateTime(DateUtils.getNowDate());
        return carPackageAuditMapper.insertCarPackageAudit(carPackageAudit);
    }

    /**
     * 修改审核列表
     * 
     * @param carPackageAudit 审核列表
     * @return 结果
     */
    @Override
    public int updateCarPackageAudit(CarPackageAudit carPackageAudit)
    {
        return carPackageAuditMapper.updateCarPackageAudit(carPackageAudit);
    }

    /**
     * 删除审核列表对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteCarPackageAuditByIds(String ids)
    {
        return carPackageAuditMapper.deleteCarPackageAuditByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除审核列表信息
     * 
     * @param id 审核列表ID
     * @return 结果
     */
    @Override
    public int deleteCarPackageAuditById(Long id)
    {
        return carPackageAuditMapper.deleteCarPackageAuditById(id);
    }

    @Override
    public CarPackageAudit getCarPackageAudit(Long id) {
        return carPackageAuditMapper.getCarPackageAudit(id);
    }

    @Override
    @Transactional
    public void cancelApply(Long carPackageAuditId) {
        //满足撤销条件
        CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditById(carPackageAuditId);
        if (audit == null || audit.getStatus().equals(CarPackageAudit.STATUS_CANCEL)){
            throw new BusinessException("参数不合法,只有非撤销状态才可以撤销");
        }
        //审核记录对象表变动
        audit.setStatus(CarPackageAudit.STATUS_CANCEL);
        audit.setAuditors("");
        carPackageAuditMapper.updateCarPackageAudit(audit);
        //套餐服务对象变动
        //修改状态为初始化
        String json = audit.getServiceItemInfo();
        ServiceItem serviceItem = JSON.parseObject(json, ServiceItem.class);
        serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        //乐观锁概念
        serviceItemService.updateStatus(serviceItem.getId(),serviceItem.getAuditStatus());
        //审核流程变动
        processService.deleteProcessInstance(audit.getInstanceId(),"用户撤销");

    }

    @Override
    public List<CarPackageAudit> findTodoList(CarPackageAudit carPackageAudit) {

        //1.查询当前登录用户关于汽车审核所有的待办任务总数
        long count = processService.selectTodoTaskCount(CarPackageAudit.DEFINITION_KEY, ShiroUtils.getUserId().toString());
        if(count>0){
            PageDomain pageDomain = TableSupport.buildPageRequest();
            Integer pageNum = pageDomain.getPageNum();
            Integer pageSize = pageDomain.getPageSize();

            //2.查询当前登录用户关于汽车审核所有的待办任务集合
            List<Task> taskList = processService
                    .selectTodoTaskList(CarPackageAudit.DEFINITION_KEY,
                            ShiroUtils.getUserId().toString(),
                            (pageNum-1)*pageSize,
                            pageSize);
            //3.遍历待办任务,查询对应的CarPackAgeAudit
            List<CarPackageAudit> resultList = new ArrayList<>();
            CarPackageAudit audit;
            for (Task task : taskList) {
                ProcessInstance processInstance = processService
                        .getProcessInstanceById(task.getProcessInstanceId());
                String businessKey = processInstance.getBusinessKey();
                audit = carPackageAuditMapper.selectCarPackageAuditById(Long.parseLong(businessKey));
                audit.setTaskName(task.getName());
                audit.setTaskId(task.getId());
                audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(),ServiceItem.class));
                resultList.add(audit);
            }
            //封装成Page对象返回
            Page<CarPackageAudit> list = new Page<>();
            list.setTotal(count);
            list.setPageNum(pageNum);
            list.setPageSize(pageSize);
            list.addAll(resultList);
            return list;
        }else{
            //如果总数为0,返回空集合回去
            return Collections.EMPTY_LIST;
        }
    }

    @Override
    @Transactional
    public void complete(String taskId, Boolean auditStatus, String comment) {

        boolean auditStatusBoolean = BooleanUtils.toBoolean(auditStatus);
        String commentStr = auditStatusBoolean?"【同意】":"【拒绝】";
        if(StringUtils.hasLength(comment)){
            commentStr += comment;
        }

        //对流程:task领取,执行task(添加备注) 对下一个节点进行数据准备(变量/候选人)
        //套餐明细状态(审核中有可能不变,也有可能审核通过)
        //审核记录状态(审核中有可能不变,也有可能审核通过)

        //---------------------------------------------------------

        //1.通过taskId审核task对象
        Task task = processService.getTaskById(taskId);
        //位置1:后续需要进行修改审核记录对象状态,而流程开始时,审核对象记录id是作为busniesskey绑定在流程中的
        //所以可以通过流程实例获取审核记录对象
        ProcessInstance instance = processService.getProcessInstanceById(task.getProcessInstanceId());
        //2.领取task任务,执行task任务,添加备注,设置下一个节点变量
        processService.claimAndComplete(task,ShiroUtils.getUserId().toString(),auditStatusBoolean,commentStr);
        //3.获取下一个任务节点
        Task nextTask = processService.getTaskByInstanceId(task.getProcessInstanceId());
        //位置2
        // ProcessInstance instance = processService.getProcessInstanceById(task.getProcessInstanceId());
        String businessKey = instance.getBusinessKey();
        CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditById(Long.parseLong(businessKey));

        //4.判断任务节点是否为空
        if (nextTask != null){
            //5.如果不为空,执行下面逻辑
            //5.1判断审核auditStatus是否是同意
            List<String> names = new ArrayList<>();
            if (auditStatus){
                //5.2如果通过
                //5.2.1下一个节点审核候选人设置
                List<SysUser> auditors = definitionNodeService.queryAuditorsByTaskDefinitionKey(nextTask.getTaskDefinitionKey());
                for (SysUser auditor : auditors) {
                    processService.addCandidateUser(nextTask.getId(),auditor.getUserId().toString());
                    names.add(auditor.getUserName());
                }
            }else {
                //5.3如果不通过
                //5.3.1修改审核记录的状态-审核拒绝
                audit.setStatus(CarPackageAudit.STATUS_REJECT);
                //5.3.2修改下一个节点审核候选人-审核流程创建者
                names.add(audit.getCreateByName());
                processService.addCandidateUser(nextTask.getId(),audit.getCreateBy());
            }
            audit.setAuditors(JSON.toJSONString(names));
            carPackageAuditMapper.updateCarPackageAudit(audit);
        }else {
            //6.如果为空,说明流程结束
                //6.1套餐状态明细-审核通过
            String json = audit.getServiceItemInfo();
            ServiceItem item = JSON.parseObject(json, ServiceItem.class);
            item.setAuditStatus(ServiceItem.AUDITSTATUS_APPROVED);
            serviceItemService.updateStatus(item.getId(),item.getAuditStatus());

                //6.2修改审核记录的状态,--审核通过
            audit.setStatus(CarPackageAudit.STATUS_PASS);
            //audit.getServiceItemInfo(JSON.)
            audit.setAuditors("");//审核人
            carPackageAuditMapper.updateCarPackageAudit(audit);

        }
    }

    @Override
    @Transactional
    public void updateServiceItem(Long carPackageAuditId, ServiceItem serviceItem) {
        serviceItemService.updateServiceItemNoCondition(serviceItem);
        CarPackageAudit carPackageAudit = carPackageAuditMapper.selectCarPackageAuditById(carPackageAuditId);
        carPackageAudit.setServiceItemInfo(JSON.toJSONString(serviceItem));
        carPackageAuditMapper.updateCarPackageAudit(carPackageAudit);
    }

    @Override
    @Transactional
    public void reApply(String taskId, Long carPackageAuditId) {

        //领取任务,执行任务,设置备注
        Task task = processService.getTaskById(taskId);
        CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditById(carPackageAuditId);
        ServiceItem item = JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class);
        //设置参数money
        processService.claimAndComplete(task,ShiroUtils.getUserId().toString(),true,"重新审核");
        //下一个节点设置
        Task nextTask = processService.getTaskByInstanceId(task.getProcessInstanceId());
        processService.setVariable(nextTask,"money",item.getDiscountPrice().longValue());
        //候选人设置
        List<SysUser> auditors = definitionNodeService.queryAuditorsByTaskDefinitionKey(nextTask.getTaskDefinitionKey());
        List<String> names = new ArrayList<>();
        for (SysUser auditor : auditors) {
            processService.addCandidateUser(nextTask.getId(),auditor.getUserId().toString());
            names.add(auditor.getUserName());
        }
        //套餐信息的状态-审核中
        //审核记录状态-审核中
        audit.setAuditors(JSON.toJSONString(names));
        audit.setStatus(CarPackageAudit.STATUS_IN_ROGRESS);
        carPackageAuditMapper.updateCarPackageAudit(audit);

    }

    @Override
    @Transactional
    public List<CarPackageAudit> findDoneList(CarPackageAudit carPackageAudit) {

        List<CarPackageAudit> list = new ArrayList<>();
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        Integer startNum = (pageNum - 1) * pageSize;
        List<HistoricTaskInstance> tasks = processService.selectDoneTaskList(CarPackageAudit.DEFINITION_KEY,
                ShiroUtils.getUserId().toString(),startNum,pageSize);
        //3.遍历待办任务,查询对应的CarPackAgeAudit
        for (HistoricTaskInstance task : tasks) {
            HistoricProcessInstance instance = processService.getHistoricProcessInstanceById(task.getProcessInstanceId());
            String businessKey = instance.getBusinessKey();
            CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditById(Long.parseLong(businessKey));
            System.out.println(audit);
            audit.setTaskName(task.getName());
            audit.setDoneTime(task.getEndTime());
            audit.setTaskId(task.getId());
            audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(),ServiceItem.class));
            list.add(audit);
        }
        Long total = processService.selectDoneTaskCount(CarPackageAudit.DEFINITION_KEY,ShiroUtils.getUserId().toString());
            Page<CarPackageAudit> page = new Page<>();
            page.setTotal(total);
            page.setPageNum(pageNum);
            page.setPageSize(pageSize);
            page.addAll(list);
            return page;
    }


    @Override
    @Transactional
    public List<HistoricActivity> selectHistoryList(String instanceId) {
        //查询集合
        List<HistoricActivityInstance> instanceList = processService
                .selectHistoryTaskList(instanceId);
        List<HistoricActivity> resultList = new ArrayList<>();
        //遍历集合
        for (HistoricActivityInstance instance : instanceList) {
            HistoricActivity historicActivity = new HistoricActivity();
            //拷贝属性
            BeanUtils.copyProperties(instance, historicActivity);
            //查询审核批注
            historicActivity.setComment(processService.getTaskComment(instance.getTaskId()));
            String assignee = instance.getAssignee();
            if(StringUtils.hasLength(assignee)){
                SysUser sysUser = sysUserMapper.selectUserById(Long.parseLong(assignee));
                if (sysUser != null) {
                    //设置审核人姓名
                    historicActivity.setAssigneeName(sysUser.getUserName());
                }
            }
            resultList.add(historicActivity);
        }
        return resultList;
    }
}
